#include <func.h>

typedef struct {
    int ticket;
    pthread_mutex_t mutex;
    pthread_cond_t cond;
}data_t;

void *window1(void*p)
{
    data_t *q=(data_t*)p;
    while(1)
    {
        pthread_mutex_lock(&q->mutex);
        if(q->ticket>0)
        {
            printf("there are %d tickets in 窗口1\n",q->ticket);
            q->ticket--;
            if(0==q->ticket)
            {
                pthread_cond_signal(&q->cond);
            }
            pthread_mutex_unlock(&q->mutex);
        }
        else
        {
            pthread_mutex_unlock(&q->mutex);
            break;
        }
        sleep(1);
    }
}

void *window2(void*p)
{
    data_t *q=(data_t*)p;
    while(1)
    {
        pthread_mutex_lock(&q->mutex);
        if(q->ticket>0)
        {
            printf("there are %d tickets in 窗口2\n",q->ticket);
            q->ticket--;
            if(0==q->ticket)
            {
                pthread_cond_signal(&q->cond);
            }
            pthread_mutex_unlock(&q->mutex);
        }
        else
        {
            pthread_mutex_unlock(&q->mutex);
            break;
        }
        sleep(1);
    }
}

void *reset(void*p)
{
    data_t *q=(data_t*)p;
    pthread_mutex_lock(&q->mutex);
    if(q->ticket>0)
    {
        pthread_cond_wait(&q->cond,&q->mutex);
    }
    q->ticket=20;
    pthread_mutex_unlock(&q->mutex);
}


int main()
{
    data_t d;
    d.ticket=20;
    int ret=pthread_mutex_init(&d.mutex,NULL);
    THREAD_ERR_CHECK(ret,"pthread_mutex_init");
    ret=pthread_cond_init(&d.cond,NULL);
    THREAD_ERR_CHECK(ret,"pthread_cond_init");
    pthread_t p[3];
    ret=pthread_create(&p[0],NULL,window1,(void*)&d);
    THREAD_ERR_CHECK(ret,"pthread_create1");
    ret=pthread_create(&p[1],NULL,window2,(void*)&d);
    THREAD_ERR_CHECK(ret,"pthread_create2");
    ret=pthread_create(&p[2],NULL,reset,(void*)&d);
    THREAD_ERR_CHECK(ret,"pthread_create3");
    for(int i=0;i<2;i++){
        pthread_join(p[i],NULL);
    }
    printf("i am main,ticket=%d\n",d.ticket);
    ret=pthread_mutex_destroy(&d.mutex);
    THREAD_ERR_CHECK(ret,"pthread_mutex_destroy");
    return 0;
}